﻿import { Response, ServiceConfig, route, Guid, Logger, RequestLog } from '../common';
import { Table, Order, CartItem, TableParty } from '../domain/model';
import { OrderService } from '../service/orderService';
import { TableService } from '../service/tableService';
import { CloudSyncService } from "../service/cloudSyncService";
import { WebException } from './webException';
import assert = require("assert");
import { CheckoutService } from "mpj-checkout";
import { logger } from "../domain/old_ldc/server/modules/logger";
import { RequestDataVerify } from '../common/http/router/routeDecorators';
import { DataVerification } from "./verification/baseVerification";
import { FNS } from "../common/fnc/fncManager";

export class OrderController {
    private orderSvr: OrderService;
    private tableSvr: TableService;
    private syncSvr: CloudSyncService;
    constructor() {
        this.orderSvr = ServiceConfig.Current.GetService<OrderService>("orderService");
        this.tableSvr = ServiceConfig.Current.GetService<TableService>("tableService");
        this.syncSvr = ServiceConfig.Current.GetService<CloudSyncService>("cloudSyncService");
    }

    toString() {
        return "OrderController";
    }

    @route({ method: 'get', path: '/api/order/unCheckoutOrders' })
    async getUnCheckoutOrderList(ctx, next) {
        let result = await this.orderSvr.GetUnCheckoutOrderList();
        ctx.response.body = Response.ok("获取列表成功", result);
        await next();
    }

    @route({ method: 'get', path: '/api/order/getPreOrderByMasterOrder/:id' })
    async getPreOrderByMasterOrder(ctx, next) {
        let masterOrderId = ctx.params.id;
        let result = await this.orderSvr.GetPreOrderByMasterOrder(masterOrderId);
        ctx.response.body = Response.ok("获取成功", result);
        await next();
    }

    @route({ method: 'get', path: '/api/order/getTodayOrderList/:skip/:type?' })
    async getTodayOrderList(ctx, next) {
        let orderType = ctx.params.type;
        let skip = ctx.params.skip;
        let r = await this.orderSvr.GetBusinessToday();
        let result = await this.orderSvr.GetOrderList({ orderType: orderType, fromDate: r.fromDate, toDate: r.toDate, skip: skip });
        ctx.response.body = Response.ok("获取列表成功", result);
        await next();
    }

    @route({ method: 'get', path: '/api/order/getCloseSaleOrderList/:checkoutMode' })
    async getCloseSaleOrderList(ctx, next) {
        let checkoutMode = ctx.params.checkoutMode;
        let r = await this.orderSvr.GetBusinessToday();
        let result = await this.orderSvr.GetOrderList({ orderType: "sales", fromDate: r.fromDate, toDate: r.toDate, status: "closed", checkoutMode: checkoutMode });
        ctx.response.body = Response.ok("获取列表成功", result);
        await next();
    }

    @route({ method: "get", path: "/api/order/queryOrder/:orderNo/:skip" })
    async queryOrder(ctx, next) {
        let orderNo = ctx.params.orderNo;
        let skip = ctx.params.skip;

        let result = await this.orderSvr.GetOrderList({ skip: skip, orderNo: orderNo });
        ctx.response.body = Response.ok("获取列表成功", result);

        await next();
    }

    @route({ method: "get", path: "/api/order/getPreOrderByTableGroup/:tableGroupId" })
    async getPreOrderByTableGroup(ctx, next) {
        let tableGroupId = ctx.params.tableGroupId;

        let r = await this.orderSvr.GetPreOrderByTableGroupId(tableGroupId);
        ctx.response.body = Response.ok("获取列表成功", r);

        await next();
    }

    @route({ method: "get", path: "/api/order/getSettledCheckoutOrder/:checkoutOrderId" })
    async getSettledCheckoutOrder(ctx, next) {
        let checkoutOrderId = ctx.params.checkoutOrderId;
        let result = await this.orderSvr.GetOrderById(checkoutOrderId);
        ctx.response.body = Response.ok("订单获取成功", result);
        await next();
    }

    @route({ method: "get", path: "/api/order/workShiftOrders/:fromDate/:toDate" })
    async getWorkShiftOrders(ctx, next) {
        let fromDate = ctx.params.fromDate;
        let toDate = ctx.params.toDate;
        let result = await this.orderSvr.GetWorkshiftOrders(fromDate, toDate);
        ctx.response.body = Response.ok("获取交班订单列表成功", result);
        await next();
    }

    @route({ method: "get", path: "/api/order/getOrderById/:orderId" })
    async getOrderById(ctx, next) {
        let orderId = ctx.params.orderId;
        let result = await this.orderSvr.GetOrderById(orderId);
        ctx.response.body = Response.ok("订单获取成功", result);
        await next();
    }


    /**
     * 店员宝下单
     * @param  {} 订单对象
     */
    @route({ method: 'post', path: '/api/order/ordering' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.OrderingDataVerify())
    async ordering(ctx, next) {
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let tableId = ctx.request.body.table.id;
        let preOrder: Order = ctx.request.body;

        this.checkOrder(preOrder);
        delete (<any>preOrder).user;
        delete (<any>preOrder).terminal;
        delete (<any>preOrder).table;

        //校验台桌是否满足下单的状态
        let p = [{ id: tableId, tablePartyId: preOrder.extended.tableParty.id }];
        let tableDataCollections = await this.tableSvr.VerifyTableOrdering(p, terminal);
        let data = await this.orderSvr.Ordering({
            OrderList: [{ table: tableDataCollections[0].table, tableParty: tableDataCollections[0].tableParty, preOrder: preOrder }],
            Terminal: terminal,
            User: user
        });
        let result = data.rst;

        ctx.response.body = Response.ok("下单成功", result[0].preOrder);

        let syncDataList = []
        syncDataList.push({
            id: result[0].masterOrder.id,
            body: result[0].masterOrder,
            entityName: "orders"
        });
        syncDataList.push({
            id: result[0].preOrder.id,
            body: result[0].preOrder,
            entityName: "preOrders"
        });
        syncDataList.push({
            id: result[0].table.id,
            body: result[0].table,
            entityName: "deskTable"
        });
        syncDataList.push({
            id: result[0].tableParty.id,
            body: result[0].tableParty,
            entityName: "tableParty"
        });

        this.syncSvr.DomainDataSyncPackage(syncDataList, { storeId: storeId, terminal: terminal, user: user }, { type: "tablesChanged,orderChanged", name: "pos.doOrdering" });

        FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage(data.SoldOutInventories));
        await next();
    }

    @route({ method: "post", path: "/api/order/mergerOrdering" })
    @RequestLog()
    @RequestDataVerify(new DataVerification.MergerOrderDataVerify())
    async mergerOrdering(ctx, next) {
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let orderList: { tableId: string; preOrder: Order }[] = ctx.request.body.orderList;

        //校验台桌是否满足下单的状态
        let tableDataCollections = await this.tableSvr.VerifyTableOrdering(orderList.map(x => { return { id: x.tableId, tablePartyId: "" }; }), terminal);

        let result = await this.orderSvr.Ordering({
            OrderList: orderList.map(x => {
                let tdata = tableDataCollections.find(n => n.table.id == x.tableId);
                return {
                    table: tdata.table,
                    tableParty: tdata.tableParty,
                    preOrder: x.preOrder
                };
            }),
            Terminal: terminal,
            User: user
        });

        let rep = [];
        let syncDataList: any[] = [];
        for (let r of result.rst) {
            syncDataList.push({
                id: r.masterOrder.id,
                body: r.masterOrder,
                entityName: "orders"
            });
            syncDataList.push({
                id: r.preOrder.id,
                body: r.preOrder,
                entityName: "preOrders"
            });
            syncDataList.push({
                id: r.table.id,
                body: r.table,
                entityName: "deskTable"
            });
            syncDataList.push({
                id: r.tableParty.id,
                body: r.tableParty,
                entityName: "tableParty"
            });
            rep.push(
                {
                    id: r.preOrder.id,
                    body: r.preOrder,
                    entityName: "preOrders"
                }
            );
        }

        ctx.response.body = Response.ok("下单成功", rep);
        this.syncSvr.DomainDataSyncPackage(syncDataList, { storeId: storeId, terminal: terminal, user: user }, { type: "tablesChanged,orderChanged", name: "pos.doOrdering" });
        FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage(result.SoldOutInventories));
        await next();
    }

    /**
     * 订单检测
     * @param  {} order
     */
    private checkOrder(order) {
        assert.notEqual(order, null, "下单失败，无订单信息");
        assert.notEqual(order.creator, null, "下单失败，操作人员必填");
        assert.notEqual(order.cart, null, "下单失败，购物车无商品");
        assert.notEqual(order.cart.items, null, "下单失败，购物车无商品");
        assert.notEqual(order.table, null, "下单失败，无开台记录");
        assert.notEqual(order.storeId, null, "下单失败，无店铺ID");
        assert.notEqual(order.terminal, null, "下单失败，无终端信息");
    }

    /**
     * 催菜
     * 
     * @param {any} ctx
     * @param {any} next
     * 
     * @memberOf OrderController
     */
    @route({ method: 'post', path: '/api/order/reminderOrder' })
    async reminderOrder(ctx, next) {
        let data = ctx.request.body;
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;

        let rmOrder = await this.orderSvr.Reminder(data.orderId, data.operator, data.cartItemList);
        ctx.response.body = Response.ok("催菜成功", rmOrder);
        //同步催菜数据到java云
        this.syncSvr.saveUploads(rmOrder, data.storeId, true, "orders/reminder");
        await next();
    }

    /**
     * 退单
     * 
     * @param {any} ctx
     * @param {any} next
     * 
     * @memberOf OrderController
     */
    @route({ method: 'post', path: '/api/order/refundOrder' })
    @RequestLog()
    async refundOrder(ctx, next) {
        let params: {
            cashier: { id: string, name: string },
            creator: { id: string, name: string },
            extended: {
                table: { id: string, name: string },
                tableParty: { id: string, name: string },
                headCount: number
            },
            cart: {
                items: CartItem[]
            },
            refOrderId: { id: string, type: string }[],
            storeId: string,
            terminalName: string,
            serialNo: string
        } = ctx.request.body;

        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];
        params.cashier = user;
        params.creator = user;

        //TODO:check params

        let table = await this.tableSvr.GetTableById(params.extended.table.id);
        if (table.lock) throw new WebException(this.tableSvr.GetLockErrText(table));
        let tp = await this.tableSvr.GetCurrentTableParty(table.id);
        if (tp.status == "presettled") throw new WebException('该台桌正在结算，无法退单！');
        let result = await this.orderSvr.Refund(<any>params);
        ctx.response.body = Response.ok("退单成功", result.refundOrder);

        //sync data to pos 
        this.syncSvr.DomainDataSyncPackage([
            {
                id: result.masterOrder.id,
                body: result.masterOrder,
                entityName: "orders"
            },
            {
                id: result.preOrder.id,
                body: result.preOrder,
                entityName: "preOrders"
            },
            {
                id: result.refundOrder.id,
                body: result.refundOrder,
                entityName: "preOrders"
            },
        ], {
                storeId: storeId,
                user: user,
                terminal: terminal
            }, {
                type: "orderChanged",
                name: "pos.refundTableOrderItem"
            });

        await next();
    }

    @route({ method: 'post', path: '/api/order/pickup' })
    async cookingPickUp(ctx, next) {
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];
        let data = ctx.request.body;
        data.operator = user;

        let r = await this.orderSvr.CookingPickUp(data.orderId, data.operator, data.cartItemList);
        ctx.response.body = Response.ok("叫起成功", r);

        //TODO:同步等叫叫起数据到java云

        await next();
    }

    @route({ method: 'post', path: '/api/order/makeSerialNo' })
    async makeSerialNo(ctx, next) {
        let origin = ctx.request.body.origin;
        let r = await this.orderSvr.SerialNoMaker(origin, true);
        ctx.response.body = Response.ok("获取成功！", r);
        await next();
    }

    @route({ method: 'post', path: '/api/order/recycleSerialNo' })
    async recycleSerialNo(ctx, next) {
        let serialNo: string = ctx.request.body.serialNo;
        let seed;
        let origin;
        if (serialNo.indexOf('-') > -1) {
            let s = serialNo.split("-");
            origin = s[0];
            seed = s[1];
        }
        else {
            seed = serialNo;
        }

        //await this.orderSvr.RecycleSerialNo(seed, origin);

        ctx.response.body = Response.ok("获取成功！", true);
        await next();
    }

    //临时接口结算完成后删除
    @route({ method: 'post', path: '/api/order/pushCheckoutData' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.PushCheckoutDataVerify())
    async pushCheckoutData(ctx, next) {
        let checkoutData = ctx.request.body.checkoutData;
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let isCounter = false;

        let orders = [];

        for (let item of checkoutData.children) {
            if (item.type == "orders") {
                if (item.obj.checkout && item.obj.checkout.terminal) {
                    let terminalId = item.obj.checkout.terminal.id;
                    let terminalName = item.obj.checkout.terminal.name;
                    item.obj.checkout.terminal = {
                        id: terminalId,
                        name: terminalName
                    };
                }
                if (item.obj.isCounter) isCounter = true; // 反结算订单不需要再次开始清台
                orders.push(item);
            }
        }

        let result = await this.orderSvr.BatchCheckout(orders, user, terminal);

        if (!isCounter && result.tablePartyIds.length > 0) {
            await this.tableSvr.StartCleanTable({ tablePartyIds: result.tablePartyIds });
        }

        ctx.response.body = Response.ok("操作成功！", result.tableIds);
        await next();
    }

    //临时接口结算完成后删除 赠送接口
    @route({ method: 'post', path: '/api/order/singleDiscount' })
    async singleDiscount(ctx, next) {
        let preOrder = ctx.request.body.preOrder;
        let masterOrder = await this.orderSvr.SingleDiscount(preOrder);
        ctx.response.body = Response.ok("操作成功！", masterOrder);

        await next();
    }

    //临时接口 - 反结算
    @route({ method: 'post', path: '/api/order/counterOrder' })
    async counterOrder(ctx, next) {
        let order = ctx.request.body.order;
        let result = await this.orderSvr.counterOrder(order);
        ctx.response.body = Response.ok("操作成功！", result);
        await next();
    }

}